package com.cleaningcloud.cld.service.impl.mini;

import com.cleaningcloud.cld.domain.*;
import com.cleaningcloud.cld.domain.dto.*;
import com.cleaningcloud.cld.domain.mini.AttStaffInfo;
import com.cleaningcloud.cld.domain.mini.CheckInResult;
import com.cleaningcloud.cld.domain.mini.HolidayData;
import com.cleaningcloud.cld.domain.mini.HolidayDto;
import com.cleaningcloud.cld.domain.vo.*;
import com.cleaningcloud.cld.mapper.*;
import com.cleaningcloud.cld.mapper.mini.MiniSalaryMapper;
import com.cleaningcloud.cld.service.*;
import com.cleaningcloud.cld.service.mini.IMiniSalaryService;
import com.cleaningcloud.cld.utils.AttendanceConversionUtils;
import com.cleaningcloud.common.core.utils.DateUtils;
import com.cleaningcloud.common.core.utils.StringUtils;
import com.cleaningcloud.common.security.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class MiniSalaryServiceImpl implements IMiniSalaryService {

    @Autowired
    private MiniSalaryMapper miniSalaryMapper;

    @Autowired
    private CldProjectMapper cldProjectMapper;

    @Autowired
    private CldProjectPostMapper cldProjectPostMapper;

    @Autowired
    private CldCalendarMapper cldCalendarMapper;

    @Autowired
    private CldClassesMapper cldClassesMapper;

    @Autowired
    private ICldProjectSetService cldProjectSetService;

    @Autowired
    private CldRestbreaksMapper restbreaksMapper;

    @Autowired
    private CldRestbreaksCalendarMemberMapper cldRestbreaksCalendarMemberMapper;

    @Autowired
    private CldOvertimeDetailsMapper cldOvertimeDetailsMapper;

    @Autowired
    private ICldOvertimeService overtimeService;

    @Autowired
    private CldAttendanceMapper cldAttendanceMapper;

    @Autowired
    private ICldLeaveService cldLeaveService;

    @Autowired
    private ICldReplaceService cldReplaceService;

    @Autowired
    private ICldRewardsService cldRewardsService;

    @Autowired
    private ICldPayConfirmService cldPayConfirmService;

    @Autowired
    private ICldAttendanceService cldAttendanceService;

    @Autowired
    private ICldTaskService cldTaskService;

    @Autowired
    private CldOvertimeMapper cldOvertimeMapper;

    @Override
    public List<HolidayData> selectHolidayList(HolidayDto holidayDto) {
        return miniSalaryMapper.selectHolidayList(holidayDto);
    }

    @Override
    public List<CldRestbreaksVo> getScheduleDetails(CldRestbreaksDto cldRestbreaksDto) {
        return miniSalaryMapper.getScheduleDetails(cldRestbreaksDto);
    }

    @Override
    public int addSchedule(CldRestbreaksDto cldRestbreaksDto) {
        // 查询项目配置
        CldProjectSet cldProjectSet = cldProjectSetService.selectCldProjectSetByProjectId(cldRestbreaksDto.getProjectId());
        if (cldProjectSet == null) {
            throw new RuntimeException("项目配置查询失败！");
        }
        // 根据当前排休年份排休月份项目id查询排休计划
        CldRestbreaksDto query = new CldRestbreaksDto();
        query.setRestbreakYear(cldRestbreaksDto.getRestbreakYear());
        query.setRestbreakMonth(cldRestbreaksDto.getRestbreakMonth());
        query.setProjectId(cldRestbreaksDto.getProjectId());
        List<CldRestbreaksVo> restbreaksList = restbreaksMapper.selectCldRestbreaksList(query);
        if (!restbreaksList.isEmpty()) {
            CldRestbreaksVo cldRestbreaksVo = restbreaksList.get(0);
            cldRestbreaksDto.setRestbreakId(cldRestbreaksVo.getRestbreakId());
        } else {
            cldRestbreaksDto.setCreateTime(DateUtils.getNowDate());
            cldRestbreaksDto.setIsConfirm(0L);
            cldRestbreaksDto.setCreateId(SecurityUtils.getUserId());
            cldRestbreaksDto.setCreateName(SecurityUtils.getUsername());
            cldRestbreaksDto.setFlag(0L);
            cldRestbreaksDto.setPlatform(2L);
            restbreaksMapper.insertCldRestbreaks(cldRestbreaksDto);
        }
        // 新增当月日历信息
        for (CldCalendarDto cldCalendarDto : cldRestbreaksDto.getCalendarList()) {
            if (cldCalendarDto.getStaffList() != null && !cldCalendarDto.getStaffList().isEmpty()) {
                if (StringUtils.isNotEmpty(cldCalendarDto.getCalendayType()) && cldCalendarDto.getCalendayType().equals("2") && cldProjectSet.getIsHolidayRest() == 1) {
                    throw new RuntimeException("当前项目配置为节假日休息,无需排休！");
                }
                // 判断是否周六休 及双休
                if (cldCalendarDto.getWeekDay() != null) {
                    if (cldCalendarDto.getWeekDay() == 6 && cldProjectSet.getIsWeekendRest() == 1) {
                        throw new RuntimeException("当前项目配置为周六休息,无需排休！");
                    }
                    if (cldCalendarDto.getWeekDay() == 7 && cldProjectSet.getIsWeekendRest() == 2) {
                        throw new RuntimeException("当前项目配置为周日休息,无需排休！");
                    }
                    if ((cldCalendarDto.getWeekDay() == 6 || cldCalendarDto.getWeekDay() == 7) && cldProjectSet.getIsWeekendRest() == 3) {
                        throw new RuntimeException("当前项目配置为周末双休,无需排休！");
                    }
                }
                // 新增排休人员数组
                List<CldRestbreaksCalendarMemberDto> addList = new ArrayList<>();
                cldCalendarDto.getStaffList().forEach(item -> {
                    item.setRestbreaksStaffId(SecurityUtils.getUserId());
                    item.setRestbreaksId(cldRestbreaksDto.getRestbreakId());
                    item.setRestbreaksCalendarId(cldCalendarDto.getCalendarId());
                    // 查询当前人员当月已排休次数
                    int count = cldRestbreaksCalendarMemberMapper.selectCountByStaffIdAndRestbreaksId(item.getProjectStaffId(), item.getRestbreaksId());
                    // 判断每人月休次数
                    if (count >= cldProjectSet.getAllMonthlyDay()) {
                        throw new RuntimeException("人员[" + item.getStaffName() + "]已排休" + count + "次，当月排休次数已达上限");
                    }
                    // 查询当前排休计划人员
                    int dayCount = cldRestbreaksCalendarMemberMapper.selectCountByStaffIdAndRestbreaksIdAndDate(item.getProjectStaffId(), item.getRestbreaksId(), item.getRestbreaksCalendarId());
                    if (dayCount == 0) {
                        addList.add(item);
                    }
                });
                if (!addList.isEmpty()) {
                    cldRestbreaksCalendarMemberMapper.batchInsertRestbreaksCalendarStaff(addList);
                }
            }
        }
        return 1;
    }

    /**
     * @Author Shaw
     * @Description 修改排休
     * @date: 2025-10-13 10:53
     * @param: //TODO
     */
    @Override
    public int updateSchedule(CldRestbreaksDto cldRestbreaksDto) {
        int result = 0;
        // 查询项目配置
        CldProjectSet cldProjectSet = cldProjectSetService.selectCldProjectSetByProjectId(cldRestbreaksDto.getProjectId());
        if (cldProjectSet == null) {
            throw new RuntimeException("项目配置查询失败！");
        }
        // 根据当前排休年份排休月份项目id查询排休计划
        CldRestbreaksDto query = new CldRestbreaksDto();
        query.setRestbreakYear(cldRestbreaksDto.getRestbreakYear());
        query.setRestbreakMonth(cldRestbreaksDto.getRestbreakMonth());
        query.setProjectId(cldRestbreaksDto.getProjectId());
        List<CldRestbreaksVo> restbreaksList = restbreaksMapper.selectCldRestbreaksList(query);
        if (!restbreaksList.isEmpty() && !cldRestbreaksDto.getCalendarList().isEmpty()) {
            for (CldCalendarDto cldCalendarDto : cldRestbreaksDto.getCalendarList()) {
                if(!cldCalendarDto.getStaffList().isEmpty()) {
                    //删除原有排休计划人员信息
                    for (CldRestbreaksCalendarMemberDto delStaff : cldCalendarDto.getStaffList()){
                        CldRestbreaksCalendarMemberDto calendarMember = new CldRestbreaksCalendarMemberDto();
                        calendarMember.setRestbreaksId(restbreaksList.get(0).getRestbreakId());
                        calendarMember.setProjectStaffId(delStaff.getProjectStaffId());
                        calendarMember.setProjectPostId(delStaff.getProjectPostId());
                        List<CldRestbreaksCalendarMemberVo> delList = cldRestbreaksCalendarMemberMapper.selectCldRestbreaksCalendarMemberList(calendarMember);
                        if(!delList.isEmpty()) {
                            for (CldRestbreaksCalendarMemberVo vo : delList) {
                                cldRestbreaksCalendarMemberMapper.deleteCldRestbreaksCalendarMemberByRestbreaksCalendarMemberId(vo.getRestbreaksCalendarMemberId());
                            }
                        }
                    }
                }
            }


            for (CldCalendarDto cldCalendarDto : cldRestbreaksDto.getCalendarList()) {
                if(!cldCalendarDto.getStaffList().isEmpty()) {
                    //新增现在排休计划人员信息
                    for (CldRestbreaksCalendarMemberDto addStaff : cldCalendarDto.getStaffList()) {
                        CldRestbreaksCalendarMember addCalendarMember = new CldRestbreaksCalendarMember();
                        addCalendarMember.setRestbreaksId(restbreaksList.get(0).getRestbreakId());
                        addCalendarMember.setProjectPostId(addStaff.getProjectPostId());
                        addCalendarMember.setProjectGroupId(addStaff.getProjectGroupId());
                        addCalendarMember.setProjectStaffId(addStaff.getProjectStaffId());
                        addCalendarMember.setRestbreaksCalendarId(cldCalendarDto.getCalendarId());
                        addCalendarMember.setRestbreaksStaffId(SecurityUtils.getUserId());
                        result = cldRestbreaksCalendarMemberMapper.insertCldRestbreaksCalendarMember(addCalendarMember);
                    }
                }
            }
        }
        return result;
    }


    @Override
    public List<CldOvertimeVo> getWorkOvertimeList(CldOvertimeDto cldOvertimeDto) {
        return overtimeService.selectCldOvertimeList(cldOvertimeDto);
    }

    @Override
    public List<CldOvertimeDetailsVo> getAuditOvertimeList(CldOvertimeDetailsDto cldOvertimeDetailsDto) {
        return cldOvertimeDetailsMapper.selectCldOvertimeDetailsList(cldOvertimeDetailsDto);
    }

    @Override
    public CldOvertimeVo getWorkOvertimeInfo(Long overTimeId) {
        CldOvertimeVo overtime = cldOvertimeMapper.selectCldOvertimeByOvertimeId(overTimeId);
        if(null != overtime){
            CldOvertimeDetailsVo vo = new CldOvertimeDetailsVo();
            vo.setOvertimeId(overTimeId);
            List<CldOvertimeDetailsVo> detailsList = cldOvertimeMapper.getCldOvertimeDetailsByOvertimeId(vo);
            if(!detailsList.isEmpty()){
                overtime.setDetailsList(detailsList);
            }else{
                throw new RuntimeException("未找到加班明细数据");
            }
        }
        return overtime;
    }

    @Override
    public CldOvertimeVo getWorkOvertimeDetails(CldOvertimeDetailsVo cldOvertimeDetailsVo) {
        return overtimeService.selectCldOvertimeByOvertimeId(cldOvertimeDetailsVo);
    }

    @Override
    public CldOvertimeDetailsVo getAuditOvertimeDetails(Long overtimeDetailsId) {
        CldOvertimeDetailsVo vo = cldOvertimeDetailsMapper.getOvertimeDetailsInfoByDetailsId(overtimeDetailsId);
        if(null != vo){
            if(null != vo.getAttendanceId()){
                List<CldAttendance> attendanceVos = cldAttendanceMapper.getOvertimeDetailsAttendanceByAttendanceIds(vo.getAttendanceId());
                if(!attendanceVos.isEmpty()){
                    vo.setAttList(attendanceVos);
                }
            }
        }
        return vo;
    }

    @Override
    public int addWorkOvertime(CldOvertimeDto cldOvertimeDto) {
        return overtimeService.insertCldOvertime(cldOvertimeDto);
    }

    @Override
    public int auditWorkOvertime(CldOvertimeDetails cldOvertimeDetails) {
        return overtimeService.auditCldOvertime(cldOvertimeDetails);
    }

    @Override
    @Transactional
    public int editWorkOvertimeCheck(List<CldAttendance> list) {
        for (CldAttendance attendance : list) {
            cldAttendanceMapper.updateCldAttendance(attendance);
        }
        return 1;
    }

    @Override
    public List<CldOvertimeDetailsVo> getConfirmOvertimeList(CldOvertimeDetailsDto cldOvertimeDetailsDto) {
        cldOvertimeDetailsDto.setStaffId(SecurityUtils.getUserId());
        return cldOvertimeDetailsMapper.selectCldOvertimeDetailsList(cldOvertimeDetailsDto);
    }

    @Override
    public int confirmWorkOvertime(CldOvertimeDetails cldOvertimeDetails) {
        cldOvertimeDetails.setIsConfrim(1L);
        return cldOvertimeDetailsMapper.updateCldOvertimeDetails(cldOvertimeDetails);
    }

    @Override
    public int addLeave(CldLeaveDto cldLeaveDto) {
        cldLeaveDto.setStaffId(SecurityUtils.getUserId());
        return cldLeaveService.insertCldLeave(cldLeaveDto);
    }

    @Override
    public List<CldLeaveVo> getLeaveList(CldLeaveDto cldLeaveDto) {
        return cldLeaveService.selectCldLeaveList(cldLeaveDto);
    }

    @Override
    public int auditLeave(CldLeaveDto cldLeaveDto) {
        return cldLeaveService.auditCldLeave(cldLeaveDto);
    }

    @Override
    public CldLeaveVo getLeaveDetails(Long leaveId) {
        return cldLeaveService.selectCldLeaveByLeaveId(leaveId);
    }

    @Override
    public int addReplacement(CldReplaceDto cldReplaceDto) {
        cldReplaceDto.setStaffId(SecurityUtils.getUserId());
        return cldReplaceService.insertCldReplace(cldReplaceDto);
    }

    @Override
    public List<CldReplaceVo> getReplacementList(CldReplaceDto cldReplaceDto) {
        return cldReplaceService.selectCldReplaceList(cldReplaceDto);
    }

    @Override
    public CldReplaceVo getReplacementDetails(Long replaceId) {
        return cldReplaceService.selectCldReplaceByReplaceId(replaceId);
    }

    @Override
    public int auditReplacement(CldReplaceDto cldReplaceDto) {
        return cldReplaceService.auditCldReplace(cldReplaceDto);
    }

    @Override
    public List<CldRewardsVo> getRewardsList(CldRewardsDto cldRewardsDto) {
        return cldRewardsService.selectCldRewardsList(cldRewardsDto);
    }

    @Override
    public int addRewards(CldRewardsDto cldRewardsDto) {
        return cldRewardsService.insertCldRewards(cldRewardsDto);
    }

    @Override
    public CldRewardsVo getRewardsDetails(Long rewardsId) {
        return cldRewardsService.selectCldRewardsByRewardsId(rewardsId);
    }

    @Override
    public int auditRewards(CldRewardsDto cldRewardsDto) {
        return cldRewardsService.auditCldRewards(cldRewardsDto);
    }

    @Override
    public Map<String, Object> selectDailySalary(CldPayConfirm cldPayConfirm) {
        cldPayConfirm.setStaffId(cldPayConfirm.getStaffId() != null ? cldPayConfirm.getStaffId() : SecurityUtils.getUserId());
        return miniSalaryMapper.selectDailySalary(cldPayConfirm);
    }

    @Override
    public int dailySalaryConfirmation(CldPayConfirm cldPayConfirm) {
        cldPayConfirm.setIsConfirm(1L);
        cldPayConfirm.setConfirmTime(DateUtils.getNowDate());
        return cldPayConfirmService.updateCldPayConfirm(cldPayConfirm);
    }

    @Override
    public List<Map<String, Object>> selectSalaryList(CldPayConfirmDto cldPayConfirm) {
        return miniSalaryMapper.selectSalaryList(cldPayConfirm);
    }

    @Override
    public List<Map<String, Object>> selectSalaryDetails(CldPayConfirm cldPayConfirm) {
        return miniSalaryMapper.selectSalaryDetails(cldPayConfirm);
    }

    @Override
    public CldAttendanceVo getAttendanceInformation(CldAttendanceDto cldAttendanceDto) {
        cldAttendanceDto.setStaffId(SecurityUtils.getUserId());
        CldAttendanceVo cldAttendanceVo = cldAttendanceMapper.getAttendanceInformation(cldAttendanceDto);
        if (cldAttendanceVo == null) {
            // 查询项目配置
            CldProjectSet cldProjectSet = cldProjectSetService.selectCldProjectSetByProjectId(cldAttendanceDto.getProjectId());
            if (cldProjectSet == null) {
                throw new RuntimeException("项目配置查询失败！");
            }
            // 查询人员岗位信息
            CldProjectPostDto cldProjectPostDto = new CldProjectPostDto();
            cldProjectPostDto.setProjectId(cldProjectPostDto.getProjectId());
            cldProjectPostDto.setIsMasterDuits(1L);
            cldProjectPostDto.setStaffId(SecurityUtils.getUserId());
            List<CldProjectPostSetVo> cldProjectPostList = cldProjectPostMapper.selectCldProjectPostList(cldProjectPostDto);
            if (cldProjectPostList.isEmpty()) {
                throw new RuntimeException("岗位信息查询失败！");
            }
            // 查询当日日历信息
            CldCalendar calendarQuery = new CldCalendar();
            calendarQuery.setCalendarYear(cldAttendanceDto.getAttendanceYear());
            calendarQuery.setCalendayMonth(cldAttendanceDto.getAttendanceMonth());
            calendarQuery.setCalendayDay(cldAttendanceDto.getAttendanceDay());
            CldCalendar calendar = cldCalendarMapper.selectCldCalendarByLimit(calendarQuery);
            cldAttendanceVo = cldTaskService.assemblyAttendance(cldAttendanceDto.getProjectId(), cldProjectPostList.get(0), cldProjectSet, calendar);
        }
        AttendanceConversionUtils.AttendanceConversion(cldAttendanceVo);
        // 判断是否可打卡
        cldAttendanceVo.setIsCheckIn(AttendanceConversionUtils.isCheckIn(cldAttendanceVo, cldAttendanceDto.getLng(), cldAttendanceDto.getLat()));
        return cldAttendanceVo;
    }

    @Override
    public CldProject getClockInInfo(Long projectId) {
        return cldProjectMapper.selectCldProjectByProjectId(projectId);
    }

    @Override
    public List<CldAttendanceVo> selectAttendanceList(CldAttendanceDto cldAttendanceDto) {
        List<CldAttendanceVo> list = cldAttendanceMapper.selectCldAttendanceList(cldAttendanceDto);
        for (CldAttendanceVo cldAttendanceVo : list) {
            AttendanceConversionUtils.AttendanceConversion(cldAttendanceVo);
        }
        return list;
    }

    @Override
    public List<CldAttendanceVo> selectAbnormalAttendanceList(CldAttendanceDto cldAttendanceDto) {
        return cldAttendanceMapper.selectCldAttendanceList(cldAttendanceDto);
    }

    @Override
    public int checkIn(CldAttendanceDto cldAttendanceDto) {
        LocalDate localDate = LocalDate.now();
        // 获取考勤信息
        CldAttendanceVo cldAttendance = cldAttendanceService.selectCldAttendanceByAttendanceId(cldAttendanceDto.getAttendanceId());
        if (cldAttendance == null) {
            throw new RuntimeException("考勤信息查询失败！");
        }
//        if (cldAttendance.getAttendanceDay() != localDate.getDayOfMonth()) {
//            throw new RuntimeException("请在当日完成考勤打卡！");
//        }
        // 获取打卡判断
        CheckInResult checkInResult = AttendanceConversionUtils.isCheckIn(cldAttendance, cldAttendanceDto.getLng(), cldAttendanceDto.getLat());
        if (!checkInResult.isCheckIn()) {
            throw new RuntimeException(checkInResult.getErrorMsg());
        }
        AttendanceConversionUtils.checkIn(cldAttendance, checkInResult);
        return cldAttendanceService.updateCldAttendance(cldAttendance);
    }


    @Override
    public CheckInResult isCheckIn(Long attendanceId, BigDecimal lng, BigDecimal lat) {
        CldAttendanceVo cldAttendanceVo = cldAttendanceMapper.selectCldAttendanceByAttendanceId(attendanceId);
        if (cldAttendanceVo == null) {
            throw new RuntimeException("考勤信息查询失败！");
        }
        return AttendanceConversionUtils.isCheckIn(cldAttendanceVo, lng, lat);
    }

    @Override
    public List<Map<String, Object>> selectAttStaff(CldAttendance cldAttendance) {
        return miniSalaryMapper.selectAttStaff(cldAttendance);
    }

    @Override
    @Transactional
    public int editAttStaff(AttStaffInfo attStaffInfo) {
        // 先批量修改未出勤
        miniSalaryMapper.batchUpdateAttStaff(attStaffInfo.getProjectId(), attStaffInfo.getAttDate());
        // 批量设置出勤人员
        miniSalaryMapper.batchSetAttStaff(attStaffInfo.getAttId());
        return 1;
    }

    private void insertCalendarMember(CldRestbreaksDto cldRestbreaks) {

        for (CldCalendarDto cldCalendarDto : cldRestbreaks.getCalendarList()) {
            // 批量删除
            cldRestbreaksCalendarMemberMapper.batchDeleteByCalendarIdAndGroupIdAndRestbreakId(cldCalendarDto.getCalendarId(), cldRestbreaks.getRestbreakId(), cldRestbreaks.getGroupName());
            if (cldCalendarDto.getStaffList() != null && !cldCalendarDto.getStaffList().isEmpty()) {
                cldCalendarDto.getStaffList().forEach(item -> {
                    item.setRestbreaksStaffId(SecurityUtils.getUserId());
                    item.setRestbreaksId(cldRestbreaks.getRestbreakId());
                    item.setRestbreaksCalendarId(cldCalendarDto.getCalendarId());
                });
                cldRestbreaksCalendarMemberMapper.batchInsertRestbreaksCalendarStaff(cldCalendarDto.getStaffList());
            }
        }
    }

    /**
     * @Author Shaw
     * @Description 根据岗位获取班次信息
     * @date: 2025-09-30 16:00
     * @param: //TODO
     */
    @Override
    public Map<String, Object> getClassesInfoMap(CldClasses cldClasses) {
        return cldClassesMapper.getClassesInfoMap(cldClasses);
    }
}
